package com.shiroha.account.config.security.keycloak;

import jakarta.ws.rs.core.Response;
import lombok.AllArgsConstructor;
import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.KeycloakBuilder;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.GroupRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@AllArgsConstructor
public class KeycloakAdminClient {

    private final Keycloak keycloak;
    private final KeycloakProperties keycloakProperties;

    private String realm() {
        return keycloakProperties.getRealm();
    }

    /**
     * 使用客户端凭证模式获取用户的访问令牌
     * @param username 用户名
     * @param password 密码
     * @return 访问令牌、刷新令牌
     *
     */
    public AccessTokenResponse fetchToken(String username, String password) throws KeycloakException {
        Keycloak keycloak = Keycloak.getInstance(
                keycloakProperties.getAuthServerUrl(),
                realm(),
                username,
                password,
                keycloakProperties.getClientId(),
                keycloakProperties.getClientSecret()
        );

        try {
            AccessTokenResponse tokenResponse = keycloak.tokenManager().grantToken();
            keycloak.close();
            return tokenResponse;
        } catch (Exception e) {
            throw new KeycloakException("获取token失败", KeycloakErrorCode.ERR_AUTH_FAILED);
        }
    }

    /**
     * 刷新token
     * @param refreshToken
     * refreshToken
     * @return
     * 新token
     */
    public AccessTokenResponse refreshToken(String refreshToken) throws KeycloakException {
        Keycloak keycloak = KeycloakBuilder.builder()
                .serverUrl(keycloakProperties.getAuthServerUrl())
                .realm(keycloakProperties.getRealm())
                .clientId(keycloakProperties.getClientId())
                .clientSecret(keycloakProperties.getClientSecret())
                .grantType(OAuth2Constants.REFRESH_TOKEN)
                .authorization(refreshToken)
                .build();
        try {
            AccessTokenResponse response = keycloak.tokenManager().refreshToken();
            keycloak.close();
            return response;
        } catch (Exception e) {
            throw new KeycloakException("刷新token失败", KeycloakErrorCode.ERR_AUTH_FAILED);
        }
    }

    /**
     * 用户登出
     * @param userId 用户id
     */
    public void logout(String userId) {
        realmResource().users().get(userId).logout();
    }

    /**
     * 返回域资源，用于对域内用户和群组进行管理
     */
    private RealmResource realmResource() {
        return keycloak.realm(realm());
    }

    // ------------------- 用户相关操作 -------------------

    /**
     * 新建用户
     * @param user 用户
     * @return 创建成功的用户，包含用户id
     */
    public UserRepresentation createUser(UserRepresentation user) {
        RealmResource realmResource = realmResource();
        try (Response response = realmResource.users().create(user)) {
            int statusCode = response.getStatus();
            if (statusCode == 201) {
                // 创建成功
                String userId = response.getLocation().getPath().replaceAll(".*/([^/]+)$", "$1"); // 从Location中提取用户ID
                user.setId(userId);
                return user;
            } else if (statusCode == 409) {
                throw new KeycloakException("用户已经存在", KeycloakErrorCode.ERR_USER_CREATION_FAILED);
            } else {
                throw new KeycloakException("用户创建失败" + statusCode, KeycloakErrorCode.ERR_USER_CREATION_FAILED);
            }
        } catch (KeycloakException e) {
            throw e;
        } catch (Exception e) {
            throw new KeycloakException("访问 Keycloak 失败", KeycloakErrorCode.ERR_KEYCLOAK_ACCESS_FAILED);
        }
    }

    /**
     * 获取用户
     * @param userId 用户id
     * @return 用户
     */
    public UserRepresentation getUserById(String userId) {
        return realmResource().users().get(userId).toRepresentation();
    }

    /**
     * 获取用户
     * @param username 用户名
     * @return 用户
     */
    public UserRepresentation getUserByUsername(String username) {
        return realmResource().users().searchByUsername(username, true).getFirst();
    }

    /**
     * 获取所有用户
     * @return 用户列表
     */
    public List<UserRepresentation> getAllUsers() {
        return realmResource().users().list();
    }

    /**
     * 更新用户
     * @param user 用户信息
     */
    public void updateUser(UserRepresentation user) {
        try {
            realmResource().users().get(user.getId()).update(user);
        } catch (Exception e) {
            throw new KeycloakException("更新用户失败", KeycloakErrorCode.ERR_KEYCLOAK_ACCESS_FAILED);
        }
    }

    /**
     * 删除用户
     * @param userId 用户id
     */
    public void deleteUser(String userId) {
        realmResource().users().get(userId).remove();
    }

    /**
     * 更新密码
     * @param userId 用户id
     * @param password 新密码
     */
    public void resetPassword(String userId, String password) {
        CredentialRepresentation credential = new CredentialRepresentation();
        credential.setType(CredentialRepresentation.PASSWORD);
        credential.setValue(password);
        credential.setTemporary(false);

        try {
            UserRepresentation user = getUserById(userId);
            if (user == null) {
                throw new KeycloakException("用户不存在", KeycloakErrorCode.ERR_USER_NOT_FOUND);
            }
            realmResource().users().get(user.getId()).resetPassword(credential);
        } catch (KeycloakException e) {
            throw e;
        } catch (Exception e) {
            throw new KeycloakException("密码修改异常", KeycloakErrorCode.ERR_RESET_PASSWORD);
        }
    }

    /**
     * 获取用户角色列表
     * @param userId 用户id
     * @return 权限列表
     */
    public List<RoleRepresentation> getUserRoles(String userId) {
        return realmResource()
                .users()
                .get(userId)
                .roles()
                .realmLevel()
                .listAll();
    }

    /**
     * 为用户分配角色
     * @param userId 用户id
     * @param roles 要分配的角色列表
     */
    public void assignRolesToUser(String userId, List<RoleRepresentation> roles) {
        keycloak.realm(realm())
                .users()
                .get(userId)
                .roles()
                .realmLevel()
                .add(roles);
    }

    /**
     * 移除用户的角色
     * @param userId 用户id
     * @param roles 要移除的角色列表
     */
    public void removeRolesFromUser(String userId, List<RoleRepresentation> roles) {
        keycloak.realm(realm())
                .users()
                .get(userId)
                .roles()
                .realmLevel()
                .remove(roles);
    }

    /**
     * 获取所有可用的角色列表
     * @return 角色列表
     */
    public List<RoleRepresentation> getAllRoles() {
        return keycloak.realm(realm())
                .roles()
                .list();
    }

    // ------------------- 群组相关操作 -------------------

    /**
     *
     * 群组后期没时间写，这边对应de1无用了，故删除
     */

    // 关闭 Keycloak 实例
    public void close() {
        if (keycloak != null) {
            keycloak.close();
        }
    }
}
